﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace Tanks.Common
{
    /// <summary>
    /// This class will contain misc methods for the game
    /// </summary>
    public class Helper
    {
        /// <summary>
        /// This method will take the colors from a sprite and will transfer it into a 2D array
        /// Original code from Riemers
        /// </summary>
        /// <param name="texture"></param>
        /// <returns></returns>
        public static Color[,] TextureTo2DArray(Texture2D texture)
        {
            Color[] colors1D = new Color[texture.Width * texture.Height];
            texture.GetData(colors1D);

            Color[,] colors2D = new Color[texture.Width, texture.Height];
            for (int x = 0; x < texture.Width; x++)
                for (int y = 0; y < texture.Height; y++)
                    colors2D[x, y] = colors1D[x + y * texture.Width];

            return colors2D;
        }

        /// <summary>
        /// This method will set x and Y coordinates from the screen and will look for the right position in the logical game matrix
        /// </summary>
        /// <param name="x">x position in the screen</param>
        /// <param name="y">y position in the screen</param>
        /// <param name="gameHeight"></param>
        /// <param name="gameWidth"></param>
        /// <param name="cellFactor"></param>
        /// <returns>a point to be used within the paintedSquares matrix</returns>
        public static Point GetGameCoordinates(int x, int y, int gameHeight, int gameWidth, int cellFactor)
        {
            var point = new Point((int)Math.Floor(((double)x / (double)gameHeight) * cellFactor), (int)Math.Floor(((double)y / (double)gameWidth) * cellFactor));
            return point;
        }

        public static Vector2 GetInvertGameCoordinates(int x, int y, int gameHeight, int gridSize, int cellFactor, PlayerStartPosition position)
        {
            float squareSide = ((float)gameHeight / (float)cellFactor);
            float xPos = x * squareSide;
            float yPos = y * squareSide; ;
            xPos = x >= 3 ? xPos + 1 : xPos;
            yPos = y >= 3 ? yPos + 1 : yPos;
            switch (position)
            {
                case PlayerStartPosition.UpLeft: break; // by default this is topleft
                case PlayerStartPosition.Centered:
                    xPos += squareSide / 2;
                    yPos += squareSide / 2;
                    break;
                case PlayerStartPosition.Bottom:
                    xPos += squareSide / 2;
                    yPos += squareSide;
                    break;
                default: break;
            }

            var point = new Vector2(xPos, yPos);
            return point;
        }


        /// <summary>
        /// Shows if a an Object is out of screen
        /// </summary>
        /// <param name="position"></param>
        /// <param name="gameHeight"></param>
        /// <param name="gameWidth"></param>
        /// <returns></returns>
        public static bool IsOutOfScreen(Vector2 position, int gameHeight, int gameWidth)
        {
            bool OutOfScreen = position.Y > gameHeight;
            OutOfScreen |= position.X < 0;
            OutOfScreen |= position.X > gameWidth;
            OutOfScreen |= position.Y < 0;

            return OutOfScreen;
        }

        /// <summary>
        /// This method will compare if two images collide by comparing the pixels positinos and color
        /// They will collide if pixelA and pixelB are in teh same coordinate and they are both non transparent
        /// Used to Collide with the tanks
        /// </summary>
        /// <param name="imageA">All pixels from Image A</param>
        /// <param name="imageAMatrix">Matrix from Image A</param>
        /// <param name="imageB">All pixels from Image B</param>
        /// <param name="imageBMatrix">Matrix from ImageB</param>
        /// <returns>Point XY where the collission occurred (-1,-1) if the collission did not occurred</returns>
        public static Vector2 TexturesCollide(Color[,] imageA, Matrix imageAMatrix, Color[,] imageB, Matrix imageBMatrix)
        {

            // Lets use this matrix to obtain the inverse pixel position wihtin the image.
            Matrix mat1to2 = imageAMatrix * Matrix.Invert(imageBMatrix);

            // ImageA H&W
            int width1 = imageA.GetLength(0); // Dimension Zero (Width)
            int height1 = imageA.GetLength(1); // Dimension One (Height)

            // ImageB H&W
            int width2 = imageB.GetLength(0);
            int height2 = imageB.GetLength(1);

            // Loop first horitontally
            for (int x1 = 0; x1 < width1; x1++)
            {
                // loop the by row (vertically)
                for (int y1 = 0; y1 < height1; y1++)
                {
                    // Find Coordinates (X,Y) of image A
                    Vector2 pos1 = new Vector2(x1, y1);

                    // Find Coordinates of Image B (X,Y)
                    Vector2 pos2 = Vector2.Transform(pos1, mat1to2);

                    // ImageB Coordinates in terms of X and Y
                    int x2 = (int)pos2.X;
                    int y2 = (int)pos2.Y;

                    if ((x2 >= 0) && (x2 < width2)) // check if it is in image boundary
                    {
                        if ((y2 >= 0) && (y2 < height2)) // check if it is in image boundary
                        {
                            if (imageA[x1, y1].A > 0) // Check Alpha of first Image A is not Transparent (Greater than 0)
                            {
                                if (imageB[x2, y2].A > 0) // Check Alpha of second Image B is not Transparent (Greater than 0)
                                {

                                    // This means both are non transparent, so there is a collission!!!
                                    // return rhe X and Y position using transformation matrix
                                    Vector2 screenPos = Vector2.Transform(pos1, imageAMatrix);
                                    return screenPos;
                                }
                            }
                        }
                    }
                }
            }

            // If there was no collition, then return this dummy vector.
            return new Vector2(-1, -1);
        }
    }
}
